using System;
using System.Collections.Generic;
using System.IO;
using System.Security.AccessControl;
using EnvDTE;
using EnvDTE80;

namespace IncrementalSave
{
    public class FileHistorySaveProvider
    {
        public string IncrementalDirectoryName { get; set; }
        private DTE _dte;

        public FileHistorySaveProvider(IncrementalSavePackage package)
        {
            _dte = package.Dte;
        }

        public bool IncrementalSave(HistoryItem historyItem)
        {
            string rootDirPath = _dte.Solution.FileName != string.Empty ? Path.GetDirectoryName(_dte.Solution.FileName) : Path.GetDirectoryName(historyItem.DocumentFilePath);
            if(rootDirPath == null)
                throw new InvalidOperationException("No directory to save incremental files");
            string incrementalDirPath = Path.Combine(rootDirPath, IncrementalDirectoryName); //SolutionDirectory/_Incremental
            string relativeDirPath = historyItem.DocumentFilePath.Substring(rootDirPath.Length + 1);//ProjectPath/FileName.cs
            string incrementalFilePath = Path.Combine(incrementalDirPath, relativeDirPath);//SolutionDirectory/_incremental/ProjectPath/FileName.cs
            string incrementalFileDirPath = Path.GetDirectoryName(incrementalFilePath); //SolutionDirecotry/_incremental/ProjectPath
            var saveDirectory = FindOrCreateDirectory(incrementalFileDirPath);
            string incrementalFilePath2 = Path.Combine(incrementalFileDirPath, string.Format("{0}_{1}", historyItem.DocumentName, historyItem.SaveTime.Ticks));
            var f = File.CreateText(incrementalFilePath2);
            f.Write(historyItem.FileText);
            f.Close();
            historyItem.IncrementalFilePath = incrementalFilePath2;
            return true;
        }

        public IEnumerable<HistoryItem> LoadHistory()
        {
            List<HistoryItem> items = new List<HistoryItem>();
            string rootDir;
            if (_dte.Solution.FileName != string.Empty) 
                rootDir = Path.GetDirectoryName(_dte.Solution.FileName);
            else
            {
                return items;
            }
            if (rootDir == null)
                throw new InvalidOperationException("No directory to save incremental files");
            string path = Path.Combine(rootDir, IncrementalDirectoryName);
            var saveDirectory = FindOrCreateDirectory(path);
            return LoadHistory(path);
        }

        private IEnumerable<HistoryItem> LoadHistory(string rootDir)
        {
            List<HistoryItem> items = new List<HistoryItem>();
            var saveDirectory = new DirectoryInfo(rootDir);
            var files = saveDirectory.GetFiles();
            foreach (FileInfo fileInfo in files)
            {
                string incrementalFileName = fileInfo.Name;
                int indexSeperator = incrementalFileName.LastIndexOf('_');
                string fileName = incrementalFileName.Substring(0, indexSeperator);
                string timestamp = incrementalFileName.Substring(indexSeperator + 1);
                string docFileDirPath = PathHelper.RemovePart(rootDir, IncrementalDirectoryName);
                string docFilePath = Path.Combine(docFileDirPath, fileName);
                //ProjectItem foundProjectItem = _dte.Solution.FindProjectItem(Path.Combine(rootDir, fileName));
                //string docFilePath = foundProjectItem.Document.FullName;
                DateTime saveTime = new DateTime(long.Parse(timestamp));

                //load file contents
                string contents;
                using (StreamReader streamReader = fileInfo.OpenText())
                {
                    contents = streamReader.ReadToEnd();
                }

                items.Add(new HistoryItem() {DocumentFilePath = docFilePath, SaveTime = saveTime, IncrementalFilePath = fileInfo.FullName, FileText = contents});
            }

            foreach (DirectoryInfo directoryInfo in saveDirectory.GetDirectories())
            {
                var childItems = LoadHistory(directoryInfo.FullName);
                items.AddRange(childItems);
            }

            return items;
        }

        private DirectoryInfo FindOrCreateDirectory(string path)
        {
            DirectoryInfo directory = new DirectoryInfo(path);
            if (!directory.Exists)
            {
                directory.Create();
            }
            directory.Attributes = FileAttributes.Hidden;
            return directory;
        }
    }
}